// ==UserScript==
// @name         小红书探索页面数据抓取器增强版
// @namespace    http://tampermonkey.net/
// @version      1.3
// @description  自动滚动小红书探索页面，抓取信息流数据（含博主昵称、发布日期），去重后支持Excel导出
// @author       You
// @match        https://www.xiaohongshu.com/**
// @require      https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js
// @require      https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_addStyle
// ==/UserScript==

(function() {
    'use strict';

    // 配置项 - 增强版选择器
    const CONFIG = {
        scrollSpeed: 50, // 像素/秒
        checkInterval: 3000, // 抓取间隔(毫秒)
        maxScrollDuration: 30000000, // 最大滚动时长(毫秒)
        selectors: {
            // 信息流卡片选择器
            feedCard: '.note-item, [class*="note"], .feed-item, [data-video-id], [class*="card"]',

            // 标题选择器
            title: '.title, [class*="title"], h1, h2, h3, h4, a[href*="/explore/"]',

            // 图片选择器
            image: 'img[src*="xiaohongshu"], img[src*="xhscdn"], img, .cover-image, [class*="image"], [class*="img"]',

            // 点赞数选择器
            likes: '[class*="like"], [class*="count"], .like-count, .interact-item, button span',

            // 博主昵称选择器
            author: '[class*="author"], [class*="user"], .user-name, .author-info, [class*="nickname"], [class*="name"]',

            // 发布日期选择器
            date: '[class*="date"], [class*="time"], .publish-time, [class*="publish"], [class*="created"]'
        }
    };

    // 状态变量
    let state = {
        isScrolling: true,
        isPaused: false,
        collectedData: [],
        scrollInterval: null,
        checkInterval: null,
        startTime: null
    };

    // 初始化
    function init() {
        // 加载之前保存的数据
        loadSavedData();

        // 创建UI控制面板
        createControlPanel();

        // 启动自动功能
        startAutoScroll();
        startDataCollection();

        console.log('🐾 小红书数据抓取脚本已启动（增强版）');
        console.log(`📊 已有数据: ${state.collectedData.length} 条`);
        console.log('🆕 新增字段: 博主昵称、发布日期');
    }

    // 创建控制面板
    function createControlPanel() {
        GM_addStyle(`
            .xs-data-control-panel {
                position: fixed;
                top: 100px;
                right: 20px;
                background: rgba(255, 255, 255, 0.95);
                border: 2px solid #ff2442;
                border-radius: 10px;
                padding: 15px;
                z-index: 10000;
                font-family: system-ui, -apple-system, sans-serif;
                box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
                min-width: 250px;
                backdrop-filter: blur(10px);
            }
            .xs-control-title {
                font-size: 16px;
                font-weight: bold;
                color: #ff2442;
                margin-bottom: 10px;
                text-align: center;
            }
            .xs-control-btn {
                width: 100%;
                padding: 8px 12px;
                border: none;
                border-radius: 6px;
                cursor: pointer;
                font-size: 13px;
                margin-bottom: 8px;
                transition: all 0.3s;
            }
            .xs-control-btn:hover {
                transform: translateY(-1px);
                box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
            }
            .xs-btn-primary {
                background: #ff2442;
                color: white;
            }
            .xs-btn-secondary {
                background: #4CAF50;
                color: white;
            }
            .xs-btn-warning {
                background: #ff9800;
                color: white;
            }
            .xs-btn-danger {
                background: #f44336;
                color: white;
            }
            .xs-status-info {
                font-size: 11px;
                color: #666;
                text-align: center;
                margin-top: 5px;
                line-height: 1.4;
            }
            .xs-field-display {
                background: #f5f5f5;
                border-radius: 4px;
                padding: 8px;
                margin-top: 8px;
                font-size: 10px;
            }
        `);

        const panel = document.createElement('div');
        panel.className = 'xs-data-control-panel';
        panel.innerHTML = `
            <div class="xs-control-title">小红书数据抓取增强版</div>
            <button id="xsToggleScroll" class="xs-control-btn xs-btn-primary">暂停滚动</button>
            <button id="xsExportExcel" class="xs-control-btn xs-btn-secondary">导出Excel</button>
            <button id="xsClearData" class="xs-control-btn xs-btn-warning">清空数据</button>
            <button id="xsDebugInfo" class="xs-control-btn xs-btn-danger">调试信息</button>
            <div class="xs-status-info">
                <div>速度: ${CONFIG.scrollSpeed}px/秒 | 抓取: 3秒/次</div>
                <div id="xsDataCount">已收集: ${state.collectedData.length} 条</div>
                <div id="xsStatus">状态: 运行中</div>
            </div>
            <div class="xs-field-display">
                <div>抓取字段: 标题、图片、点赞、博主、日期</div>
                <div>去重方式: 标题+博主组合去重</div>
            </div>
        `;

        document.body.appendChild(panel);

        // 事件监听
        document.getElementById('xsToggleScroll').addEventListener('click', toggleScroll);
        document.getElementById('xsExportExcel').addEventListener('click', exportToExcel);
        document.getElementById('xsClearData').addEventListener('click', clearData);
        document.getElementById('xsDebugInfo').addEventListener('click', showDebugInfo);
    }

    // 自动滚动功能
    function startAutoScroll() {
        state.startTime = Date.now();

        state.scrollInterval = setInterval(() => {
            if (state.isScrolling && !state.isPaused) {
                window.scrollBy(0, 1);

                // 检查是否滚动到底部
                if ((window.innerHeight + window.scrollY) >= document.documentElement.scrollHeight - 10) {
                    console.log('📜 已滚动到页面底部，停止滚动');
                    state.isScrolling = false;
                    updateStatus('已到底部');
                }

                // 检查最大时长
                // if (Date.now() - state.startTime > CONFIG.maxScrollDuration) {
                //     console.log('⏰ 达到最大滚动时长，停止滚动');
                //     state.isScrolling = false;
                //     updateStatus('时间到已停止');
                // }
            }
        }, 1000 / CONFIG.scrollSpeed);
    }

    // 数据抓取功能
    function startDataCollection() {
        // 立即执行一次
        collectData();

        state.checkInterval = setInterval(collectData, CONFIG.checkInterval);
    }

    // 收集数据
    function collectData() {
        if (state.isPaused) return;

        try {
            const newData = [];
            const cards = document.querySelectorAll(CONFIG.selectors.feedCard);

            console.log(`🔍 发现 ${cards.length} 个潜在卡片`);

            cards.forEach((card, index) => {
                if (index > 50) return; // 限制处理数量

                const data = extractCardData(card, index);
                if (data && data.title) {
                    // 基于标题+博主组合去重
                    if (!isDuplicate(data.title, data.author)) {
                        newData.push(data);
                    }
                }
            });

            if (newData.length > 0) {
                state.collectedData = state.collectedData.concat(newData);
                saveData();

                console.group(`🆕 新增 ${newData.length} 条数据 (总计: ${state.collectedData.length})`);
                newData.forEach(item => {
                    console.log(`📝 ${item.title} - 👤 ${item.author} - 📅 ${item.publishDate} - 👍 ${item.likes}`);
                });
                console.groupEnd();

                updateDataCount();
            }

        } catch (error) {
            console.error('数据抓取错误:', error);
        }
    }

    // 提取卡片数据 - 增强版
    function extractCardData(card, index) {
        try {
            // 提取标题
            let title = extractTextContent(card, CONFIG.selectors.title.split(', '));

            // 提取博主昵称
            let author = extractTextContent(card, CONFIG.selectors.author.split(', '));

            // 提取发布日期
            let publishDate = extractTextContent(card, CONFIG.selectors.date.split(', '));

            // 清理日期格式
            publishDate = cleanDate(publishDate);

            // 提取图片
            let imageUrl = extractImageUrl(card);

            // 提取点赞数
            let likes = extractLikes(card);

            if (title) {
                return {
                    id: `card_${Date.now()}_${index}`,
                    title: title.substring(0, 200),
                    author: author || '未知博主',
                    publishDate: publishDate || '未知日期',
                    imageUrl: imageUrl || '未找到',
                    likes: likes,
                    timestamp: new Date().toISOString(),
                    source: window.location.href
                };
            }

            return null;
        } catch (error) {
            console.error(`提取卡片数据出错:`, error);
            return null;
        }
    }

    // 提取文本内容
    function extractTextContent(element, selectors) {
        for (let selector of selectors) {
            const found = element.querySelector(selector);
            if (found) {
                const text = found.textContent.trim();
                if (text && text.length > 0) {
                    return text;
                }
            }
        }
        return '';
    }

    // 提取图片URL
    function extractImageUrl(element) {
        for (let selector of CONFIG.selectors.image.split(', ')) {
            const img = element.querySelector(selector);
            if (img) {
                const url = img.src || img.getAttribute('data-src') || img.getAttribute('data-original') || '';
                if (url && url.includes('http')) {
                    return url.split('?')[0]; // 去除URL参数
                }
            }
        }
        return '';
    }

    // 提取点赞数
    function extractLikes(element) {
        for (let selector of CONFIG.selectors.likes.split(', ')) {
            const elements = element.querySelectorAll(selector);
            for (let el of elements) {
                const text = el.textContent.trim();
                const likeMatch = text.match(/(\d+(\.\d+)?)[万wk]?/);
                if (likeMatch) {
                    let num = parseFloat(likeMatch[1]);
                    if (text.includes('万') || text.includes('w')) num *= 10000;
                    if (text.includes('k')) num *= 1000;
                    return Math.round(num);
                }
            }
        }
        return 0;
    }

    // 清理日期格式
    function cleanDate(dateString) {
        if (!dateString) return '';

        // 处理相对时间（如"3天前"）
        if (dateString.includes('前')) {
            const now = new Date();
            if (dateString.includes('分钟')) {
                const mins = parseInt(dateString) || 0;
                now.setMinutes(now.getMinutes() - mins);
                return now.toISOString().split('T')[0];
            } else if (dateString.includes('小时')) {
                const hours = parseInt(dateString) || 0;
                now.setHours(now.getHours() - hours);
                return now.toISOString().split('T')[0];
            } else if (dateString.includes('天')) {
                const days = parseInt(dateString) || 0;
                now.setDate(now.getDate() - days);
                return now.toISOString().split('T')[0];
            }
        }

        // 返回原始日期（小红书通常使用"YYYY-MM-DD"格式）
        return dateString;
    }

    // 去重检查（基于标题+博主组合）
    function isDuplicate(title, author) {
        return state.collectedData.some(item =>
            item.title === title && item.author === author
        );
    }

    // 导出Excel - 增强版字段
    function exportToExcel() {
        if (state.collectedData.length === 0) {
            alert('暂无数据可导出');
            return;
        }

        try {
            // 准备数据 - 包含所有字段
            const excelData = state.collectedData.map(item => ({
                '标题': item.title,
                '博主昵称': item.author,
                '发布日期': item.publishDate,
                '点赞数': item.likes,
                '图片链接': item.imageUrl,
                '抓取时间': new Date(item.timestamp).toLocaleString('zh-CN'),
                '数据ID': item.id,
                '来源页面': item.source
            }));

            // 创建工作簿
            const worksheet = XLSX.utils.json_to_sheet(excelData);
            const workbook = XLSX.utils.book_new();
            XLSX.utils.book_append_sheet(workbook, worksheet, '小红书数据');

            // 设置列宽
            const colWidths = [
                { wch: 40 }, // 标题
                { wch: 15 }, // 博主昵称
                { wch: 12 }, // 发布日期
                { wch: 10 }, // 点赞数
                { wch: 30 }, // 图片链接
                { wch: 20 }, // 抓取时间
                { wch: 20 }, // 数据ID
                { wch: 25 }  // 来源页面
            ];
            worksheet['!cols'] = colWidths;

            // 生成文件并下载
            const filename = `小红书完整数据_${new Date().getTime()}.xlsx`;
            XLSX.writeFile(workbook, filename);

            console.log('✅ Excel文件已生成并下载:', filename);
            console.log('📋 包含字段: 标题、博主昵称、发布日期、点赞数、图片链接等');
            updateStatus('导出成功');

        } catch (error) {
            console.error('导出Excel失败:', error);
            alert('导出失败，请检查控制台错误信息');
        }
    }

    // 调试信息功能
    function showDebugInfo() {
        console.group('🐛 调试信息');
        console.log('📊 总数据量:', state.collectedData.length);
        console.log('🎯 当前选择器配置:', CONFIG.selectors);

        // 显示最近3条数据的详细信息
        const recentData = state.collectedData.slice(-20);
        console.log('🆕 最近3条数据详情:');
        recentData.forEach((item, index) => {
            console.log(`  ${index + 1}. 标题: ${item.title}`);
            console.log(`     博主: ${item.author}`);
            console.log(`     日期: ${item.publishDate}`);
            console.log(`     点赞: ${item.likes}`);
        });

        // 检查页面元素
        const cards = document.querySelectorAll(CONFIG.selectors.feedCard);
        console.log('🔍 页面卡片数量:', cards.length);

        if (cards.length > 0) {
            console.log('📝 第一个卡片HTML结构:');
            console.log(cards[0].outerHTML.substring(0, 500) + '...');
        }
        console.groupEnd();

        updateStatus('调试信息已输出');
    }

    // 工具函数
    function toggleScroll() {
        state.isScrolling = !state.isScrolling;
        const button = document.getElementById('xsToggleScroll');

        if (state.isScrolling) {
            button.textContent = '暂停滚动';
            button.className = 'xs-control-btn xs-btn-primary';
            updateStatus('运行中');
        } else {
            button.textContent = '继续滚动';
            button.className = 'xs-control-btn xs-btn-warning';
            updateStatus('已暂停');
        }
    }

    function clearData() {
        if (confirm('确定要清空所有数据吗？此操作不可撤销。')) {
            state.collectedData = [];
            saveData();
            updateDataCount();
            console.log('🗑️ 数据已清空');
            updateStatus('数据已清空');
        }
    }

    function updateDataCount() {
        const element = document.getElementById('xsDataCount');
        if (element) {
            element.textContent = `已收集: ${state.collectedData.length} 条`;
        }
    }

    function updateStatus(message) {
        const element = document.getElementById('xsStatus');
        if (element) {
            element.textContent = `状态: ${message}`;
        }
    }

    function saveData() {
        GM_setValue('xiaohongshu_collected_data', JSON.stringify(state.collectedData));
    }

    function loadSavedData() {
        try {
            const saved = GM_getValue('xiaohongshu_collected_data', '[]');
            state.collectedData = JSON.parse(saved);
        } catch (error) {
            state.collectedData = [];
            console.error('加载保存数据失败:', error);
        }
    }

    // 鼠标悬停暂停功能
    document.addEventListener('mouseover', (e) => {
        if (e.target.closest('.xs-data-control-panel')) return;
        state.isPaused = true;
        updateStatus('鼠标悬停暂停');
    });

    document.addEventListener('mouseout', (e) => {
        if (e.target.closest('.xs-data-control-panel')) return;
        state.isPaused = false;
        updateStatus('运行中');
    });

    // 初始化脚本
    window.addEventListener('load', init);

})();